import Draw from 'ol/interaction/Draw'
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
import { OSM, Vector as VectorSource } from 'ol/source'
import { getArea, getLength } from 'ol/sphere'
import { unByKey } from 'ol/Observable'
import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'
import Overlay from 'ol/Overlay'
import { LineString, Polygon } from 'ol/geom'

let layerIndex = 0
export default class Measure {
  /**
   *
   * @param map 地图
   */
  constructor(map, vector) {
    this.map = map
    this.draw = null
    this.drawCache = {}
    this.vector = vector
    this.continueLineMsg = '双击结束绘制'
    this.continuePolygonMsg = '点击绘制多边形'
    this.helpTooltipElement = null
    this.helpTooltip = null
    this.measureTooltipElement = null
    this.measureTooltip = null
  }

  //测距、测面
  measure(type) {
    this.shapeType = type
    layerIndex++
    this.drawCache[layerIndex] = {
      feature: null,
      measureTooltip: null
    }
    if (this.draw) {
      this.map.removeInteraction(this.draw)
    }
    // 添加map事件
    this.addMapEvent()
  }
  //清除测量
  clearMeasure() {
    if (layerIndex === 0) return
    for (let i in this.drawCache) {
      this.map.removeOverlay(this.drawCache[i].measureTooltip)
      this.vector.getSource().removeFeature(this.drawCache[i].feature)
    }
    this.drawCache = {}
    layerIndex = 0
    this.removeStop()
  }
  addMapEvent() {
    this.map.on('pointermove', (evt) => {
      this.draw ? this.pointerMoveHandler(evt) : this.map.removeOverlay(this.helpTooltip)
    })
    this.map.getViewport().addEventListener('mouseout', () => {
      this.helpTooltipElement && this.helpTooltipElement.classList.add('hidden')
    })
    this.addInteraction()
  }
  addInteraction() {
    this.draw = new Draw({
      source: this.vector.getSource(),
      type: this.shapeType,
      style: new Style({
        fill: new Fill({
          color: 'rgba(255, 255, 255, 0.2)'
        }),
        stroke: new Stroke({
          color: 'rgba(0, 0, 0, 0.5)',
          lineDash: [10, 10],
          width: 2
        }),
        image: new CircleStyle({
          radius: 5,
          stroke: new Stroke({
            color: 'rgba(0, 0, 0, 0.7)'
          }),
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          })
        })
      })
    })

    this.map.addInteraction(this.draw)
    this.createMeasureTooltip()
    this.createHelpTooltip()
    this.drawHandler()
  }
  /**
   * Handle pointer move.
   * @param {import("../src/ol/MapBrowserEvent").default} evt The event.
   */
  pointerMoveHandler(evt) {
    if (evt.dragging) {
      return
    }
    /** @type {string} */
    var helpMsg = '鼠标左键单击'

    if (this.sketch) {
      var geom = this.sketch.getGeometry()
      if (geom instanceof LineString) {
        helpMsg = this.continueLineMsg
      }
    }

    this.helpTooltipElement.innerHTML = helpMsg
    this.helpTooltip.setPosition(evt.coordinate)

    this.helpTooltipElement.classList.remove('hidden')
  }
  /**
   * Format length output.
   * @param {LineString} line The line.
   * @return {string} The formatted length.
   */
  formatLength(line) {
    const sourceProj = this.map.getView().getProjection() //获取投影坐标系
    var length = getLength(line, { projection: sourceProj })
    var output
    if (length > 100) {
      output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'
    } else {
      output = Math.round(length * 100) / 100 + ' ' + 'm'
    }
    return output
  }

  /**
   * Format area output.
   * @param {Polygon} polygon The polygon.
   * @return {string} Formatted area.
   */
  formatArea(polygon) {
    const sourceProj = this.map.getView().getProjection() //获取投影坐标系
    const geom = polygon.clone().transform(sourceProj, 'EPSG:3857')
    const area = getArea(geom)

    let output
    if (area > 10000) {
      output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'
    } else {
      output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
    }
    return output
  }

  /**
   * Creates a new measure tooltip
   */
  createMeasureTooltip() {
    if (this.measureTooltipElement) {
      this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement)
    }
    this.measureTooltipElement = document.createElement('div')
    this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'
    this.measureTooltip = new Overlay({
      element: this.measureTooltipElement,
      offset: [0, -15],
      positioning: 'bottom-center'
    })
    this.map.addOverlay(this.measureTooltip)
  }

  /**
   * Creates a new help tooltip
   */
  createHelpTooltip() {
    if (this.helpTooltipElement) {
      this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement)
    }
    this.helpTooltipElement = document.createElement('div')
    this.helpTooltipElement.className = 'ol-tooltip hidden'
    this.helpTooltip = new Overlay({
      element: this.helpTooltipElement,
      offset: [15, 0],
      positioning: 'center-left'
    })
    this.map.addOverlay(this.helpTooltip)
  }

  drawHandler() {
    this.draw.on('drawstart', (evt) => {
      this.sketch = evt.feature
      let tooltipCoord = evt.coordinate

      this.listener = this.sketch.getGeometry().on('change', (evt) => {
        let output
        const geom = evt.target
        if (geom instanceof LineString) {
          output = this.formatLength(geom)
          tooltipCoord = geom.getLastCoordinate()
        } else if (geom instanceof Polygon) {
          output = this.formatArea(geom)
          tooltipCoord = geom.getInteriorPoint().getCoordinates()
        }
        let closeBtn = "<i class='tooltip-close-btn tooltip-close-btn_" + layerIndex + "' data-index='" + layerIndex + "'>×</i>"
        this.measureTooltipElement.innerHTML = output + closeBtn
        this.measureTooltip.setPosition(tooltipCoord)
        this.drawCache[layerIndex].measureTooltip = this.measureTooltip
      })
    })

    this.draw.on('drawend', (evt) => {
      this.drawCache[layerIndex].feature = evt.feature

      this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'
      this.measureTooltip.setOffset([0, -7])
      // unset sketch
      this.sketch = null
      // unset tooltip so that a new one can be created
      this.measureTooltipElement = null
      this.createMeasureTooltip()
      unByKey(this.listener)
      this.map.removeInteraction(this.draw)
      this.draw = null

      // 删除图层
      const self = this
      document.querySelector('.tooltip-close-btn_' + layerIndex).addEventListener('click', function () {
        self.vector.getSource().removeFeature(self.drawCache[this.dataset.index].feature)
        self.map.removeOverlay(self.drawCache[this.dataset.index].measureTooltip)
        delete self.drawCache[this.dataset.index]
      })
    })
  }
  //结束绘制
  removeStop() {
    this.map.removeInteraction(this.draw)
    this.draw = null
  }
}
